home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / pctjoc85.arc / WHERE.C < prev    next >
Text File  |  1985-07-25  |  16KB  |  409 lines

  1. /***************************************************************
  2. *                                   *
  3. *       WHERE                           *
  4. *                                   *
  5. * Where is a program to locate files on the PC hard disk.      *
  6. * It requires DOS 2.x or 3.x.                         *
  7. *                                   *
  8. * The command line syntax is:                       *
  9. * where [starting directory]filename.ext               *
  10. *                                   *
  11. * Written by Mark S. Ackerman                       *
  12. *                                   *
  13. * Copyright 1984, 1985 by Mark S. Ackerman.  Permission is     *
  14. * granted for unlimited copies if not sold or otherwise           *
  15. * exchanged for gain.                           *
  16. *                                   *
  17. ***************************************************************/
  18.  
  19.  
  20. /***************************************************************
  21. * The C header files                            *
  22. * These identify library routines like printf() and intcall()  *
  23. ***************************************************************/
  24.  
  25. #include <stdio.h>    /* standard i/o                  */
  26. #include <dos.h>    /* functions for DOS interrupt calls  */
  27.  
  28.  
  29. /***************************************************************
  30. * Definition of DOS Disk Transfer Area (DTA)                *
  31. ***************************************************************/
  32.  
  33. /***************************************************************
  34. * Structure for MS-DOS date and time fields               *
  35. * See pages 4-6 and 4-7 of the DOS 2.1 technical           *
  36. * reference manual for more information                   *
  37. * This structure is used in the next structure definition      *
  38. ***************************************************************/
  39.  
  40. struct msdos_date 
  41.     {
  42.     unsigned ms_sec       : 5;    /* time in 2 sec. int (5 bits)*/
  43.     unsigned ms_min       : 6;    /* minutes (6 bits)          */
  44.     unsigned ms_hour   : 5;    /* hours (5 bits)          */
  45.     unsigned ms_day       : 5;    /* day of month (5 bits)      */
  46.     unsigned ms_month  : 4;    /* month (4 bits)          */
  47.     unsigned ms_year   : 7; /* year since 1980 (7 bits)   */
  48.      };
  49.  
  50. /***************************************************************
  51. * Structure filled in by MS-DOS for interrupt 21 calls           *
  52. * See page 5-46 of the DOS 2.1 technical reference             *
  53. * manual for more information                       *
  54. ***************************************************************/
  55.  
  56. struct DTA
  57.     {
  58.     char     DTA_dosinfo[21];    /* used by DOS          */
  59.     char     DTA_attr;         /* file attribute byte   */
  60.     struct msdos_date DTA_date;  /* date struct. as above */
  61.     long     DTA_size;         /* file size          */
  62.     char     DTA_filename[13];   /* file name (w/o path)  */
  63.     };
  64.  
  65.  
  66. /***************************************************************
  67. *        Definitions of constants               *
  68. ***************************************************************/
  69.  
  70. #define not !     /* for ease of reading (C uses a ! 
  71.                     character for logical not's)              */
  72. #define and &     /* for ease of reading    (C uses a & 
  73.             character for bit-wise logical and's)     */
  74. #define carry_set 0x0001 /* mask for flag register 
  75.                 for carry bit    */
  76. #define no_type      0x00   /* no bits set on file attribute byte*/
  77. #define directory_type     0x10 /* directory file bit on file 
  78.                  info word    */
  79. #define no_more_files     18     /* DOS return code for 
  80.                     no more files             */
  81. #define end_of_string     '\0'     /* C uses a binary zero to 
  82.                       signal end of string    */
  83. #define backslash '\\'     /* the backslash character          */
  84.  
  85. char *month[] =    {
  86.         "Jan","Feb","Mar","Apr","May","Jun",
  87.         "Jul","Aug","Sep","Oct","Nov","Dec"
  88.         };
  89. char *time_of_day[2] = {"AM","PM"};
  90.  
  91.  
  92. /***************************************************************
  93. *        Define the type "filename"                *
  94. *            to be a string of 51 characters           *
  95. ***************************************************************/
  96.  
  97. typedef char filename[51];
  98.  
  99.  
  100. /***************************************************************
  101. *                                   *
  102. * The following filename strings are used in the program:      *
  103. *                                   *
  104. *    check_string        filename to be searched for    *
  105. *                filename in the command line)  *
  106. *    directory_string    directory name to be searched  *
  107. *    newdirectory_string    directory name to be searched  *
  108. *                  on next recursive call       *
  109. *    current_string        temporary string for searching *
  110. *                  in a specific directory      *
  111. ***************************************************************/
  112.  
  113. /***************************************************************
  114. * Definition of any forward-referenced functions           *
  115. ***************************************************************/
  116.  
  117. char *DATE();
  118.  
  119.  
  120. /***************************************************************
  121. *        Global variables                   *
  122. ***************************************************************/
  123.  
  124. filename check_string;    /* this string "remembers" user input */
  125. struct reg registers;    /* structure to allow access to indiv.*/
  126.             /*   registers for interrupts           */
  127. char datestring[40];    /* print output string for dates      */
  128.  
  129.  
  130. /***************************************************************
  131. *        MAIN() -- the beginning of the code            *
  132. ***************************************************************/
  133.  
  134. main(argc,argv)
  135. int argc;
  136. char *argv[];
  137.     {
  138.     filename directory_string;    /* directory to be searched   */
  139.     char *incoming_filename;    /* address of filename in 
  140.                    command line argument 
  141.                        (ie, the filename)          */
  142.     char *last_location;    /* address of last backslash in 
  143.                    command line argument      */
  144.     char *incoming_string;    /* address of 
  145.                    command line argument      */
  146.     int  last_directory_char;    /* last character
  147.                    in directory string      */
  148.  
  149. /********************************************************
  150. *    check number of incoming arguments              *        
  151. *    if incorrect, write an error message            *
  152. ********************************************************/
  153.                         
  154.     if (argc not= 2)
  155.     printf
  156.     ("usage is:   WHERE [starting directory]filename.ext\n\n");
  157.     else
  158.     {
  159. /********************************************************
  160. * incoming_string is set to the first argument in the   *
  161. * command line                                          *
  162. * The incoming_string is then searched for the last     *
  163. * occurrence of a backslash to find the end of          *
  164. * the directory name.                                   *
  165. ********************************************************/
  166.  
  167. incoming_string = *(++argv);
  168. last_location = rindex(incoming_string,backslash);
  169.  
  170. /********************************************************
  171. * If there was not a backslash (and therefore the       *
  172. *     beginning directory is the root directory)        *
  173. * begin                                                 *
  174. *   copy command line argument into check_string        *
  175. *   copy root directory into directory_string           *
  176. * end                                                   *
  177. * else                                                  *
  178. * (if there was a backslash and therefore a beginning   *
  179. *     directory specified in the command line)          *
  180. * begin                                                 *
  181. *   set the incoming_filename to the next character     *
  182. *       past the backslash                              *
  183. *   copy the incoming_filename into check_string        *
  184. *   copy the command line argument into                 *
  185. *       directory_string                                *
  186. *   terminate directory_string just after the           *
  187. *    last backslash (therefore leaving only the      *
  188. *    the directory name in the string)               *
  189. * end                                                    *
  190. ********************************************************/
  191.                 
  192. if (last_location == NULL)
  193.     {
  194.     strcpy(check_string,incoming_string);
  195.     strcpy(directory_string,"\\");
  196.     }
  197. else
  198.     {
  199.     incoming_filename = last_location + 1;
  200.     strcpy(check_string,incoming_filename);
  201.     strcpy(directory_string,incoming_string);
  202.     last_directory_char = incoming_filename - incoming_string;
  203.     directory_string[last_directory_char] = end_of_string;
  204.                     }
  205. /********************************************************
  206. *        start 'er up                            *
  207. ********************************************************/
  208.         
  209. LOOK(directory_string);
  210. }
  211. return;
  212. }          
  213.  
  214.  
  215. LOOK(directory_string)
  216.  
  217. /********************************************************
  218. *    LOOK is the recursive procedure in WHERE        *
  219. *    It is called once for each subdirectory         *
  220. ********************************************************/
  221.  
  222. char *directory_string;
  223.     {
  224.     struct DTA current_DTA;  /* used to return data from DOS  */
  225.     filename newdirectory_string; /* the directory to be 
  226.                      searched on the next
  227.                      call to LOOK()           */
  228.     filename current_string;      /* temporary filename 
  229.                      string for    searching for 
  230.                      directories          */
  231.  
  232. /********************************************************
  233. * Form current_string by copying directory_string and   *
  234. *    and then concatenating "*.*" to look through all   *
  235. *    files                                              *
  236. ********************************************************/
  237.  
  238.     strcpy(current_string,directory_string);
  239.     strcat(current_string,"*.*");
  240.  
  241. /********************************************************
  242. * Set the Disk Transfer Area in DOS to the current_DTA  *
  243. *    structure                                          *
  244. * Get the first subdirectory in this directory          *
  245. ********************************************************/
  246.  
  247.     SET_DTA(¤t_DTA);
  248.     GET_FIRST(current_string,directory_type);
  249.  
  250. /********************************************************
  251. * while there are more subdirectories in this directory *
  252. * begin                                                 *
  253. *   double check for proper directories (see text)      *
  254. *   if a directory                                      *
  255. *   begin                                               *
  256. *     set up the newdirectory_string for the            *
  257. *     next call to LOOK (see text)                      *
  258. *     call LOOK                                         *
  259. *     reset Disk Transfer Address (see text)            *
  260. *   end                                                 *
  261. *   look for next directory                             *
  262. * end                                                   *
  263. ********************************************************/
  264.  
  265.     while (not(registers.r_flags and carry_set))
  266.     {
  267.     if (current_DTA.DTA_attr == directory_type &&
  268.        current_DTA.DTA_filename[0] not= '.')
  269.         {
  270.         strcpy(newdirectory_string,directory_string);
  271.         strcat(newdirectory_string,current_DTA.DTA_filename);
  272.         strcat(newdirectory_string,"\\");
  273.         LOOK(newdirectory_string);
  274.         SET_DTA(¤t_DTA);
  275.         }
  276.     GET_NEXT();
  277.     }
  278.     
  279. /********************************************************
  280. * if there are no more subdirectories in this directory *
  281. *   look for files                                      *
  282. * else                                                  *
  283. *   print an error message                              *
  284. ********************************************************/
  285.  
  286.     if (registers.r_ax == no_more_files)
  287.     GET_FILES(directory_string,¤t_DTA);
  288.     else
  289.         printf("problem with looking thru %s\n",directory_string);
  290.     return;
  291.     }
  292.     
  293. GET_FILES(directory_string,current_DTA)
  294.  
  295. /********************************************************
  296. * GET_FILES                         *
  297. * is called once per directory to look for the         *
  298. *   actual files matching the search string        *
  299. ********************************************************/
  300.  
  301. char *directory_string;
  302. struct DTA *current_DTA;
  303.     {
  304.     filename current_string;
  305.  
  306. /********************************************************
  307. * Form current_string by copying directory_string into  *
  308. *   it and then concatenating the check_string onto     *
  309. *   the end                                             *
  310. ********************************************************/
  311.  
  312.     strcpy(current_string,directory_string);
  313.     strcat(current_string,check_string);
  314.  
  315. /********************************************************
  316. * Get the first file that matches current_string        *
  317. ********************************************************/
  318.  
  319.     GET_FIRST(current_string,no_type);
  320.  
  321. /********************************************************
  322. * while there are more files that match the search      *
  323. *   string:                                             *
  324. * begin                                                 *
  325. *   print the file information                          *
  326. *   get the next file                                   *
  327. * end                                                   *
  328. ********************************************************/
  329.  
  330.     while (not(registers.r_flags and carry_set))
  331.     {
  332.     printf(" %10D  %s  %s%s\n", (*current_DTA).DTA_size,
  333.        DATE(&((*current_DTA).DTA_date)), directory_string,
  334.        (*current_DTA).DTA_filename);
  335.         GET_NEXT();
  336.     }
  337. /********************************************************
  338. * if error in looking for a file                        *
  339. *    print error message and return                     *
  340. ********************************************************/
  341.  
  342.     if (registers.r_ax not= no_more_files)
  343.         printf("problem with looking for %s\n",current_string);
  344.     return;
  345.     }
  346.  
  347.  
  348. GET_NEXT()
  349.     {
  350. /********************************************************
  351. * GET_NEXT does an interrupt 21h, function 4Fh          *
  352. ********************************************************/
  353.  
  354.     registers.r_ax = 0x4f00;
  355.     intcall(®isters,®isters,0x21);
  356.     return;
  357.     }
  358.  
  359. SET_DTA(current_DTA)
  360.     struct DTA *current_DTA;
  361.     {
  362. /********************************************************
  363. * SET_DTA does an interrupt 21h, function 1Ah           *
  364. *   The DS:DX pair is set to the address of the         *
  365. *   current_DTA data structure                          *
  366. ********************************************************/
  367.  
  368.     registers.r_ax = 0x1a00;
  369.     ptoreg(dsreg,registers.r_dx,registers.r_ds,current_DTA);
  370.     intcall(®isters,®isters,0x21);
  371.     return;
  372.     }
  373.  
  374. GET_FIRST(search_string,filetype)
  375.     char *search_string;
  376.     int filetype;
  377.     {
  378. /********************************************************
  379. * GET_FIRST does an interrupt 21h, function 4Eh         *
  380. *   The CX register is set to either normal or          *
  381. *   directory type (see text)                           *
  382. *   The DS:DX pair is set to the address of the         *
  383. *   search string                                       *
  384. ********************************************************/
  385.     registers.r_ax = 0x4e00;
  386.     registers.r_cx = filetype;
  387.     ptoreg(dsreg,registers.r_dx,registers.r_ds,search_string);
  388.     intcall(®isters,®isters,0x21);        
  389.     return;
  390.     }
  391.  
  392.     
  393. char *DATE(dateptr)
  394. struct msdos_date *dateptr;
  395.     {
  396. /********************************************************
  397. * DATE takes the date field from the current DTA        *
  398. *   structure and returns a string containing the       *
  399. *   information in formatted ASCII                      *
  400. ********************************************************/
  401.  
  402.     sprintf(datestring, "%02d-%02d-%2d  %02d:%02d %s",
  403.     dateptr->ms_month, dateptr->ms_day,
  404.     dateptr->ms_year+80, (dateptr->ms_hour)%12, 
  405.         dateptr->ms_min, time_of_day[((dateptr->ms_hour)/12)]);
  406.     return(datestring);
  407.     }
  408.  
  409.